package com.qire.manhua.model.viewModel.impl;

import android.content.res.ColorStateList;
import android.graphics.Color;
import android.view.View;

import com.qire.common.basic.ObjectUtil;
import com.qire.common.basic.StringUtil;
import com.qire.common.collect.ListUtil;
import com.qire.common.concurrent.IntervalRunWrapper;
import com.qire.common.concurrent.ThreadUtil;
import com.qire.common.model.entity.UserEntity;
import com.qire.common.support.SmartRefreshViewModel;
import com.qire.common.support.base.IViewModel;
import com.qire.common.widget.adapter.auto.AutoVariable;
import com.qire.common.widget.adapter.auto.SummerPagerAdapter;
import com.qire.common.widget.adapter.auto.SummerRecyclerBindAdapter;
import com.qire.common.widget.adapter.auto.annotation.AdapterEntityBind;
import com.qire.manhua.R;
import com.qire.manhua.controller.BookshelfFavoritesController;
import com.qire.manhua.databinding.LayoutHomeBookshelfBannerItemBinding;
import com.qire.manhua.databinding.LayoutHomeBookshelfBannerSigninBinding;
import com.qire.manhua.databinding.LayoutHomeBookshelfFavoritesItemBinding;
import com.qire.manhua.model.entity.ComicBookEntity;
import com.qire.manhua.dal.service.HomeBookshelfFavoritesService;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import androidx.lifecycle.MutableLiveData;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView.Adapter;
import androidx.recyclerview.widget.RecyclerView.LayoutManager;
import androidx.viewpager.widget.PagerAdapter;

public class BookshelfFavoritesViewModel extends SmartRefreshViewModel<IViewModel> {

    /**
     * 数据服务
     */
    private final HomeBookshelfFavoritesService favoritesService = new HomeBookshelfFavoritesService(this);

    /**
     * banner 自动轮换程序
     */
    private final BannerLoopPlayer bannerLoopPlayer = new BannerLoopPlayer();

    /** 收藏项目 */
    private final ArrayList<FavoritesItemViewModel> favoritesItemViewModelList = new ArrayList<>();
    /** 收藏数据的适配器 */
    private final SummerRecyclerBindAdapter<FavoritesItemViewModel> favoritesAdapter = new SummerRecyclerBindAdapter<>(favoritesItemViewModelList);
    /** 选中删除数量 */
    private final ArrayList<String> batchDeleteList = new ArrayList<>();

    /** 编辑状态 */
    private boolean isEditing = false;

    /** 数据异常状态 */
    private boolean isException = false;

    private BookshelfViewModel bookshelfViewModel;

    //region    #附加管理 begin
    /**
     * 附加属性绑定
     */
    public void onAddition(BookshelfFavoritesController controller) {
        bannerLoopPlayer.setEventProcess(controller);
        favoritesAdapter.setEventProcess(controller);
        refreshUI();
    }

    /**
     * 清理函数，在Activity退出时，ViewModel生命周期到期会被回收，调用该事件，页面由于切换、横竖屏转换、内存回收等情况并不会影响到ViewModel的生命周期。
     */
    @Override
    protected void onCleared() {
        super.onCleared();
        bannerLoopPlayer.setEventProcess(null);
        favoritesAdapter.setEventProcess(null);
    }
    //endregion #附加管理 end

    //region    #业务数据处理 begin
    /**
     * 加载轮播数据，包含 1. 签到信息 2. banner广告
     */
    public void loadCarouselData() {
        // 停止轮播循环，避免更新数组时异常
        bannerLoopPlayer.stopLoop();
        // 重置轮播列表，以便获取接口信息后出现重复数据
        bannerLoopPlayer.reset();
        if(UserEntity.self.isLogin()) {
            // 获取签到信息
            favoritesService.fetchSignInInfo();
            // 加载banner广告数据
            favoritesService.fetchBannerList();
        } else {
            refreshBannerPlateUI();
        }
    }

    /**
     * 更新轮播中签到信息卡
     */
    public void updateSignInInfo(boolean isSignIn, boolean isFirstSignIn, int todayBeans, int tomorrowBeans) {
        // 登录状态且没有签到，才需要显示签到提示
        if(UserEntity.self.isLogin() && !isSignIn) {
            bannerLoopPlayer.addFirstItem(new SignInViewModel(isFirstSignIn, todayBeans, tomorrowBeans));
        }
    }

    /**
     * 添加banner推荐项
     * @param comicBookEntity 漫画实体
     * @param tips 提示
     * @param bannerCover 封面
     */
    public void addBannerItem(ComicBookEntity comicBookEntity, String tips, String bannerCover) {
        bannerLoopPlayer.addItem(new BannerItemViewModel(comicBookEntity, tips, bannerCover));
    }

    public void bannerAdapterNotifyDataChanged(boolean signInReady, boolean bannerReady) {
        if(signInReady) {
            bannerLoopPlayer.signInReady();
        }
        if(bannerReady) {
            bannerLoopPlayer.bannerReady();
        }
        bannerLoopPlayer.startLoop();
        refreshBannerPlateUI();
    }

    /**
     * 加载收藏夹数据
     */
    public void loadFavoritesData() {
        // 清除数据
        clearFavoritesData();
        // 如果未登录则刷新空数据面板
        if(!UserEntity.self.isLogin()) {
            refreshLayoutFinish(300);
            refreshEmptyDataUI(false);
            return;
        }

        favoritesService.fetchFavoritesList();
    }

    private void clearFavoritesData() {
        favoritesAdapter.notifyItemRangeRemoved(0, favoritesItemViewModelList.size());
        favoritesItemViewModelList.clear();
        // 防止状态不同步，由于页面切换回收等情况会导致项目列表重新生成并刷新状态。
        // 如果删除选项没有清楚会导致UI于删除内容不同步的问题。如果复杂情况下应该使用实时计算来获取选中的删除项个数。
        batchDeleteList.clear();
    }

    public void addFavoritesItem(ComicBookEntity comicBookEntity, boolean isShowTips, String floatTipsText,
                                 String floatFreeDate, int lastReadChapter, int lastUpdateChapter) {
        favoritesItemViewModelList.add(new FavoritesItemViewModel(comicBookEntity, isShowTips, floatTipsText, floatFreeDate, lastReadChapter, lastUpdateChapter));
    }

    public void favoritesAdapterNotifyDataChanged() {
        favoritesAdapter.notifyItemChanged(0, "full");
    }

    public void submitDelFavorites() {
        favoritesService.submitDelFavorites(batchDeleteList);
        // 删除操作后列表列表没有可选数据时退出编辑状态
        if(ObjectUtil.nonNull(bookshelfViewModel) && batchDeleteList.size() >= favoritesItemViewModelList.size()) {
            bookshelfViewModel.closeEditMode();
        }
    }

    public void clearBatchDeleteList() {
        batchDeleteList.clear();
        refreshDeletePlateUI();
    }

    public boolean isException() {
        return isException;
    }

    public boolean isEditing() {
        return isEditing;
    }

    /**
     * 根据当前编辑状态判断下一步切换编辑状态的条件，如果没有可操作选项，则不允许进入编辑页。
     * @return true 为可进入编辑，false 不可进入编辑，只有当编辑状态位 false 且 收藏有内容时才可以编辑。
     */
    public boolean isAllowEdit() {
        return !isEditing && ListUtil.notEmpty(favoritesItemViewModelList);
    }

    public int batchDeleteCount() {
        return batchDeleteList.size();
    }

    //endregion #业务数据处理 end

    //region    #UI操作 begin

    /**
     * 切换编辑状态
     * @param isEditing true 进入编辑状态  false 退出编辑状态
     */
    public void toggleEditing(boolean isEditing) {
        this.isEditing = isEditing;
        refreshUI();
        favoritesAdapter.notifyItemRangeChanged(0, favoritesAdapter.getItemCount());
        if(!isEditing) {
            // 如果是退出编辑，则清空所有选中状态
            for(FavoritesItemViewModel itemViewModel : favoritesItemViewModelList) {
                if(itemViewModel.isChecked()) {
                    itemViewModel.toggle();
                }
            }
        }
    }

    /**
     * 切换所有收藏项选择状态
     */
    public void toggleCheckAll() {
        boolean isCheck = batchDeleteCount() == favoritesItemViewModelList.size();
        for(FavoritesItemViewModel itemViewModel : favoritesItemViewModelList) {
            if(isCheck == itemViewModel.isChecked()) {
                itemViewModel.toggle();
            }
        }
    }

    public void refreshUI() {
        refreshBannerPlateUI();
        refreshDeletePlateUI();
        refreshEmptyDataUI(false);
    }

    public void refreshBannerPlateUI() {
        set("indicatorCount", bannerLoopPlayer.size());
        // todo: 这里改成put修改，目前由于不明原因的问题会导致在设置可见切换时，引起包含的子控件 ViewPager 适配器通知修改异常导致闪退
        put("bannerPlateVisible", (!UserEntity.self.isLogin() || isEditing) ? View.GONE : View.VISIBLE);
    }

    public void refreshEmptyDataUI(boolean isException) {
        this.isException = isException;

        boolean isFavoriteEmpty = ListUtil.isEmpty(favoritesItemViewModelList);
        set("dataContentPageNo", isFavoriteEmpty ? 1 : 0);

        // 以下状态之需要考虑非正常数据的情况，因为之上已经做了页面切换，如果数据正常，则不会展示下面的内容。

        if(UserEntity.self.isLogin()) {
            set("emptyPanelIcon", isException ? R.drawable.app_common_pic_no_network : R.drawable.app_common_pic_no_favorites);
            set("emptyPanelBtnText", isException ? "点击重试" : "去书城看看");
        } else {
            set("emptyPanelIcon", R.drawable.app_common_pic_not_login);
            set("emptyPanelBtnText", "立即登录");
        }
    }

    public void refreshDeletePlateUI() {
        set("deletePlateVisible", isEditing ? View.VISIBLE : View.GONE);

        boolean isActive = ListUtil.notEmpty(batchDeleteList);

        set("deleteButtonIconColor", isActive ? ColorStateList.valueOf(Color.rgb(0xff, 0x90, 0x24)) : ColorStateList.valueOf(Color.rgb(0x5c,0x5c,0x5c)));
        set("deleteButtonText", "删除选中(" + batchDeleteCount() +")");
        set("deleteButtonTextColor", isActive ? "#ff9024" : "#5c5c5c");

        // 刷新父框架面板
        if(ObjectUtil.nonNull(bookshelfViewModel)) {
            bookshelfViewModel.toggleAllCheckUI(batchDeleteCount() >= favoritesItemViewModelList.size());
        }
    }

    public void setBookshelfViewModel(BookshelfViewModel bookshelfViewModel) {
        this.bookshelfViewModel = bookshelfViewModel;
        if(ObjectUtil.nonNull(bookshelfViewModel)) {
            bookshelfViewModel.toggleAllCheckUI(batchDeleteCount() >= favoritesItemViewModelList.size());
        }
    }

    public void setBannerIndicatorPointIndex(int index) {
        set("currentIndicatorPointIndex", index);
    }
    //endregion #UI操作 end

    //region    #UI绑定 begin
    public MutableLiveData<Integer> getBannerPlateVisible() {
        return get("bannerPlateVisible");
    }

    public MutableLiveData<Integer> getDeletePlateVisible() {
        return get("deletePlateVisible");
    }

    public MutableLiveData<ColorStateList> getDeleteButtonIconColor() {
        return get("deleteButtonIconColor");
    }

    public MutableLiveData<CharSequence> getDeleteButtonText() {
        return get("deleteButtonText");
    }

    public MutableLiveData<String> getDeleteButtonTextColor() {
        return get("deleteButtonTextColor");
    }

    public MutableLiveData<Integer> getBannerPageNo() {
        return get("bannerPageNo");
    }

    public MutableLiveData<Integer> getIndicatorCount() {
        return get("indicatorCount");
    }

    public MutableLiveData<Integer> getCurrentIndicatorPointIndex() {
        return get("currentIndicatorPointIndex");
    }

    public MutableLiveData<Integer> getDataContentPageNo() {
        return get("dataContentPageNo");
    }

    public MutableLiveData<Integer> getEmptyPanelIcon() {
        return get("emptyPanelIcon");
    }

    public MutableLiveData<String> getEmptyPanelBtnText() {
        return get("emptyPanelBtnText");
    }

    /** 轮换广告适配器 */
    public PagerAdapter getBannerAdapter() {
        return bannerLoopPlayer.bookshelfBannerAdapter;
    }
    /** 收藏夹数据适配器 */
    public Adapter getFavoritesAdapter() {
        return favoritesAdapter;
    }

    public LayoutManager getFavoritesLayoutManager() {
        return new GridLayoutManager(null, 3, GridLayoutManager.VERTICAL, false);
    }

    //endregion #UI绑定 end

    /** banner 广告循环播放器 */
    public class BannerLoopPlayer {

        /** banner广告子项 **/
        private final ArrayList<AutoVariable> bookshelfBannerList = new ArrayList();
        /** banner广告适配器 **/
        private final SummerPagerAdapter bookshelfBannerAdapter = new SummerPagerAdapter(bookshelfBannerList);
        /** 循环滚动步长，一次翻一页 */
        private final int stepLength = 1;

        private IntervalRunWrapper wrapper;
        private boolean signInReady, bannerReady;

        public void setEventProcess(AutoVariable eventProcess) {
            bookshelfBannerAdapter.setEventProcess(eventProcess);
        }

        public int size() {
            return bookshelfBannerList.size();
        }

        public void addFirstItem(AutoVariable variable) {
            bookshelfBannerList.add(0, variable);
        }

        public void addItem(AutoVariable variable) {
            bookshelfBannerList.add(variable);
        }

        public void signInReady() {
            signInReady = true;
        }
        public void bannerReady() {
            bannerReady = true;
        }

        public void startLoop() {
            if(!signInReady || !bannerReady) {
                return;
            }
            stopLoop();
            bookshelfBannerAdapter.notifyDataSetChanged();
            wrapper = ThreadUtil.<Void>interval(3, TimeUnit.SECONDS).andThen((v) -> {
                if(!wrapper.isRunning() || ListUtil.isEmpty(bookshelfBannerList)) {
                    return;
                }

                int currentPosition = getToValue("bannerPageNo", 0);
                int nextPosition = (currentPosition + stepLength) % bookshelfBannerList.size();
                put("bannerPageNo", nextPosition);

            }).accept();
        }

        public void stopLoop() {
            if(wrapper != null && wrapper.isRunning()) {
                wrapper.stop();
                wrapper = null;
            }
        }

        public void reset() {
            bookshelfBannerAdapter.clearDataAndNotifyChanged();
            signInReady = false;
            bannerReady = false;
        }

    }

    /**
     * banner位签到ViewModel
     */
    @AdapterEntityBind(viewRid = R.layout.layout_home_bookshelf_banner_signin)
    public class SignInViewModel extends BaseObservable implements AutoVariable<LayoutHomeBookshelfBannerSigninBinding> {
        private boolean isFirstSignIn;
        private int todayBeans = 0, tomorrowBeans = 0;

        public SignInViewModel(boolean isFirstSignIn, int todayBeans, int tomorrowBeans) {
            this.isFirstSignIn  = isFirstSignIn;
            this.todayBeans     = todayBeans;
            this.tomorrowBeans  = tomorrowBeans;
            notifyPropertyChanged(com.qire.manhua.BR.firstSignInTipsVisible);
            notifyPropertyChanged(com.qire.manhua.BR.todayBeansText);
            notifyPropertyChanged(com.qire.manhua.BR.tomorrowBeansText);
        }

        @Override
        public void bindVariable(LayoutHomeBookshelfBannerSigninBinding viewBind) {
            viewBind.setSignInViewModel(this);
        }

        @Bindable
        public int    getFirstSignInTipsVisible() {
            return isFirstSignIn ? View.VISIBLE : View.GONE;
        }
        @Bindable
        public String getTodayBeansText() {
            return String.valueOf(todayBeans);
        }
        @Bindable
        public String getTomorrowBeansText() {
            return String.valueOf(tomorrowBeans);
        }

    }

    /**
     * banner位推荐
     */
    @AdapterEntityBind(viewRid = R.layout.layout_home_bookshelf_banner_item)
    public class BannerItemViewModel extends BaseObservable implements AutoVariable<LayoutHomeBookshelfBannerItemBinding> {

        private final ComicBookEntity comicBookEntity;
        private final String tips;
        private final String bannerCover;

        public BannerItemViewModel(ComicBookEntity comicBookEntity, String tips, String bannerCover) {
            this.comicBookEntity = comicBookEntity;
            this.tips            = tips;
            this.bannerCover     = bannerCover;
        }

        @Override
        public void bindVariable(LayoutHomeBookshelfBannerItemBinding viewBind) {
            viewBind.setBannerItemViewModel(this);
        }

        public ComicBookEntity toComicBookEntity() {
            return  comicBookEntity;
        }

        @Bindable
        public String getTitle() {
            return comicBookEntity.bookName;
        }
        @Bindable
        public String getTips() {
            return tips;
        }
        @Bindable
        public String getBannerCover() {
            return bannerCover;
        }

    }

    /**
     * 收藏夹项目ViewModel
     */
    @AdapterEntityBind(viewRid = R.layout.layout_home_bookshelf_favorites_item)
    public class FavoritesItemViewModel extends BaseObservable implements AutoVariable<LayoutHomeBookshelfFavoritesItemBinding> {

        public final ComicBookEntity comicBookEntity;

        private final boolean   isShowTips;
        private final String    floatTipsText;
        private final String    floatFreeDate;
        private final int       lastReadChapter;
        private final int       lastUpdateChapter;

        private boolean isChecked = false;

        public FavoritesItemViewModel(ComicBookEntity comicBookEntity, boolean isShowTips, String floatTipsText, String floatFreeDate, int lastReadChapter, int lastUpdateChapter) {
            this.comicBookEntity     = comicBookEntity;
            this.isShowTips          = isShowTips;
            this.floatTipsText       = floatTipsText;
            this.floatFreeDate       = floatFreeDate;
            this.lastReadChapter     = lastReadChapter;
            this.lastUpdateChapter   = lastUpdateChapter;
        }

        @Override
        public void bindVariable(LayoutHomeBookshelfFavoritesItemBinding viewBind) {
            viewBind.setFavoritesItemViewModel(this);
        }

        public void toggle() {
            this.isChecked = !this.isChecked;
            if(isChecked) {
                batchDeleteList.add(String.valueOf(comicBookEntity.id));
            } else {
                batchDeleteList.remove(String.valueOf(comicBookEntity.id));
            }
            notifyPropertyChanged(com.qire.manhua.BR.checkMarkIcon);
            refreshDeletePlateUI();
        }

        private boolean isChecked() {
            return isChecked;
        }

        public ComicBookEntity toComicBookEntity() {
            return comicBookEntity;
        }

        @Bindable
        public String getBookCover() {
            return comicBookEntity.getCoverPlotVertical();
        }
        @Bindable
        public int getRenewIconVisible() {
            return View.GONE;
        }
        @Bindable
        public String getTitle() {
            return comicBookEntity.bookName;
        }
        @Bindable
        public String getSubtitle() {
            String current = lastReadChapter == 0 ? "未看" : lastReadChapter + "话";
            return current + "/" + lastUpdateChapter + "话";
        }
        @Bindable
        public String getFloatFreeDate() {
            return StringUtil.notEmpty(floatFreeDate) ? "剩余" + floatFreeDate : "";
        }
        @Bindable
        public String getFloatTipsText() {
            return StringUtil.defValue(floatTipsText, "");
        }
        @Bindable
        public int getCheckMarkIcon() {
            return isChecked() ? R.drawable.app_home_bookshelf_select_b : R.drawable.app_home_bookshelf_select_a;
        }
        @Bindable
        public int getCheckMarkVisible() {
            return isEditing() ? View.VISIBLE : View.GONE;
        }
        @Bindable
        public int getFloatTipsVisible() {
            if(!isShowTips)
                return View.GONE;
            return isEditing() ? View.GONE : View.VISIBLE;
        }

    }

}
